package com.zh.common.utils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Random;

/**
 * @program: CSDN
 * @description: SHA工具类
 * @author: Alian
 * @create: 2021-06-01 15:20:10
 **/
public class SHAUtil {

    private static final String SHA_1 = "SHA-1";
    private static final String SHA_224 = "SHA-224";
    private static final String SHA_256 = "SHA-256";
    private static final String SHA_384 = "SHA-384";
    private static final String SHA_512 = "SHA-512";
    private static final char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    public static String getSHA1(String painText,String salt) {
        return getShaWithSalt(painText, salt, SHA_1);
    }

    public static String getSHA224(String painText,String salt) {
        return getShaWithSalt(painText, salt, SHA_224);
    }

    public static String getSHA256(String painText,String salt) {
        return getShaWithSalt(painText, salt,SHA_256);
    }

    public static String getSHA384(String painText,String salt) {
        return getShaWithSalt(painText, salt, SHA_384);
    }

    public static String getSHA512(String painText,String salt) {
        return getShaWithSalt(painText, salt, SHA_512);
    }

    /**
     * SHA加密加盐
     *
     * @param plainText 待加密字符串
     * @param salt      盐值
     * @param algorithm 算法
     * @return 加密结果(哈希密码和盐值)
     */
    private static String getShaWithSalt(String plainText, String salt, String algorithm) {
        //生成盐
        plainText+=salt;
        //输入的字符串转换成字节数组
        byte[] bytes = plainText.getBytes(StandardCharsets.UTF_8);
        MessageDigest messageDigest;
        try {
            //获得SHA转换器
            messageDigest = MessageDigest.getInstance(algorithm);
            //bytes是输入字符串转换得到的字节数组
            messageDigest.update(bytes);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA签名过程中出现错误,算法异常");
        }
        //转换并返回结果，也是字节数组，包含16个元素
        byte[] digest = messageDigest.digest();
        //字符数组转换成字符串返回
        return byteArrayToHexString(digest);
    }

    /**
     * 将字节数组转为16进制字符串
     *
     * @param bytes 要转换的字节数组
     * @return
     */
    private static String byteArrayToHexString(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        for (byte b : bytes) {
            //java.lang.Integer.toHexString() 方法的参数是int(32位)类型，
            //如果输入一个byte(8位)类型的数字，这个方法会把这个数字的高24为也看作有效位，就会出现错误
            //如果使用& 0XFF操作，可以把高24位置0以避免这样错误
            String temp = Integer.toHexString(b & 0xFF);
            if (temp.length() == 1) {
                //1得到一位的进行补0操作
                builder.append("0");
            }
            builder.append(temp);
        }
        return builder.toString();
    }

    /**
     * 生成随机盐值
     *
     * @return 随机盐值字符串
     */
    public static String generateSalt() {
        Random random = new Random();
        byte[] saltBytes = new byte[16];
        random.nextBytes(saltBytes);
        return byteArrayToHexString(saltBytes);
    }

}
